HTMLify

index.html
Views: 119 | Author: cody
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Projectile Motion</title>
    
    <style>
        .btns, .inputs {
            margin: 20px;
        }

        input[type="number"] {
            border-radius: 10px;
            border: 2px solid #aaa;
            padding: 5px;
            font-size: 1.1em;
            margin-bottom: 10px;
        }

        button {
            border: none;
            padding: 10px 15px;
            border-radius: 5px;
            margin-right: 20px;
            color: #fff;
            font-size: 1.05em;
            font-weight: 600;
            cursor: pointer;
        }

        #launch {
            background-color: deepskyblue;
        }

        #reset {
            background-color: crimson;
        }

        .control {
            display: flex;
            align-items: center;
            flex-wrap: wrap;
            justify-content: center;
        }

        .board {
            position: relative;
            margin: 20px;
            height: 450px;
        }

        .board::before {
            content: "";
            position: absolute;
            bottom: 0;
            transform: translateY(50%);
            width: 100%;
            height: 2px;
            background-color: black;
        }

        .board::after {
            content: "";
            position: absolute;
            left: 0;
            transform: translateX(-50%);
            width: 2px;
            height: 100%;
            background-color: black;
            z-index: -1;
        }

        .x {
            position: absolute;
            bottom: 0;
            right: 0;
            transform: translateX(200%) translateY(50%);
        }

        .y {
            position: absolute;
            top: 0;
            left: 0;
            transform: translateX(-50%) translateY(-100%);
        }

        .y::before {
            position: absolute;
            content: "";
            display: inline-block;
            width: 0.6em;
            height: 0.6em;
            border-right: 0.2em solid black;
            border-top: 0.2em solid black;
            transform: rotate(-45deg);
            left: -1px;
            bottom: -14px;
        }

        .x::before {
            position: absolute;
            content: "";
            display: inline-block;
            width: 0.6em;
            height: 0.6em;
            border-right: 0.2em solid black;
            border-top: 0.2em solid black;
            transform: rotate(45deg);
            left: -23px;
            bottom: 3px;
        }

        #projectile {
            position: absolute;
            width: 30px;
            height: 30px;
            background-color: darkred;
            left: 0;
            bottom: 0;
            transform: translate(-50%, 50%);
            border-radius: 50%;
        }

        .path {
            position: absolute;
            width: 10px;
            height: 10px;
            background-color: black;
            border-radius: 50%;
            z-index: -1;
        }

        .yDist {
            position: absolute;
            transform: translate(-50%, -110%);
            background-color: black;
            color: white;
            padding: 5px;
            font-size: 1.1em;
        }

        .yDist::before {
            content: "";
            position: absolute;
            border: 10px solid black;
            border-color: black transparent transparent transparent;
            left: 50%;
            bottom: 0;
            transform: translate(-50%, 100%);
        }

        .xDist {
            position: absolute;
            transform: translate(75%, 50%);
            background-color: black;
            color: white;
            padding: 5px;
            font-size: 1.1em;
        }

        .xDist::before {
            content: "";
            position: absolute;
            border: 10px solid black;
            border-color: transparent black transparent transparent;
            left: 0;
            bottom: 50%;
            transform: translate(-100%, calc(-1px + 50%));
        }
    </style>

</head>
<body>
    <div class="control">
        <div class="inputs">
            <input type="number" name="velocity" id="velocity" placeholder="Initial Velocity">
            <input type="number" name="angle" id="angle" placeholder="Angle">
        </div>
        <div class="btns">
            <button id="launch">Launch</button>
            <button id="reset">Reset</button>
        </div>
    </div>
    <div class="board">
        <span class="x">X</span>
        <span class="y">Y</span>
        <div id="projectile"></div>
    </div>

    <script>
        
        class Projectile {
            element;
            x;
            y;
            g;
            horizontalRange;
            maxHeight;
            actualHorizontalRange;


            constructor(element, x, y) {
                this.element = element;
                this.x = x;
                this.y = y;
            }

            moveHorizontal(speed) {
                let intervalHorizontal = setInterval(() => {
                    if(this.x >= this.horizontalRange) {
                        if(this.y > 0)
                            this.horizontalRange *= 2;
                        else{

                            clearInterval(intervalHorizontal);

                            let xDist = document.createElement('div');
                            let text = document.createTextNode(this.actualHorizontalRange);
                            xDist.appendChild(text);
                            xDist.classList.add('xDist');
                            xDist.style.left = this.x + 'px';
                            xDist.style.bottom = this.y + 'px';
                            this.element.parentElement.appendChild(xDist);
                        }
                    }

                    if(this.x%25 === 0){
                        let path = document.createElement('div');
                        path.classList.add('path');
                        path.style.left = this.x + 'px';
                        path.style.bottom = this.y + 'px';
                        this.element.parentElement.appendChild(path);
                    }

                    this.x++;
                    this.element.style.left = this.x + 'px';
                }, 500/speed);
            }

            moveVertical(velocity) {

                let interval = () => new Promise(resolve => {
                    let intervalUp = () => {

                        // velocity -= this.g * 1/velocity;
                        velocity = Math.sqrt(velocity*velocity - 2*this.g);
                        
                        let oneInterval = setTimeout(intervalUp, 500/velocity);
                        
                        if(this.y >= this.maxHeight && isNaN(velocity)){
                            clearTimeout(oneInterval);

                            let yDist = document.createElement('div');
                            let text = document.createTextNode(this.maxHeight);
                            yDist.appendChild(text);
                            yDist.classList.add('yDist');
                            yDist.style.left = this.x + 'px';
                            yDist.style.bottom = this.y + 'px';
                            this.element.parentElement.appendChild(yDist);
                            
                            resolve();
                        }
                        this.y++;
                        this.element.style.bottom = this.y + 'px';
                    }

                    setTimeout(intervalUp, 500/velocity);
                });

                interval().then(() => {
                    let intervalDown = () => {

                        // velocity += this.g * 1/velocity;
                        velocity = Math.sqrt(velocity*velocity + 2*this.g);

                        let oneInterval = setTimeout(intervalDown, 500/velocity);

                        if(this.y <= 0){
                            clearTimeout(oneInterval);
                            
                            this.horizontalRange = this.x;
                        }
                        this.y--;
                        this.element.style.bottom = this.y + 'px';
                    }
                    velocity = 0;
                    // setTimeout(intervalDown, 0);
                    intervalDown();
                });
            }
        }
        
        let initVelocity = document.getElementById('velocity');
        let angle = document.getElementById('angle');

        let launch = document.getElementById('launch');
        let reset = document.getElementById('reset');

        let projectileObj = new Projectile(
            document.getElementById('projectile'),
            0,
            0
        );
        
        launch.onclick = () => {
            let initVelocityValue = parseInt(initVelocity.value);
            let angleValue = parseInt(angle.value);
            
            if(
                !isNaN(initVelocityValue) &&
                !isNaN(angleValue) &&
                initVelocityValue > 0 &&
                angleValue > 0 &&
                angleValue <= 90 &&
                !projectileObj.x &&
                !projectileObj.y
            ) {
                projectileObj.g = 9.81;

                let vx = initVelocityValue * Math.cos(Math.PI * angleValue/180);
                let vy0 = initVelocityValue * Math.sin(Math.PI * angleValue/180);
                let maxHeight = Math.round((vy0 * vy0) / (2 * projectileObj.g));
                let horizontalRange = Math.round(vx * (2 * vy0 / projectileObj.g));

                projectileObj.maxHeight = maxHeight;
                projectileObj.horizontalRange = horizontalRange;
                projectileObj.actualHorizontalRange = horizontalRange;
                
                if(Math.floor(vx) > 0) projectileObj.moveHorizontal(vx);
                projectileObj.moveVertical(vy0);
            }
        }

        window.onload = () => {
            initVelocity.value = '';
            angle.value = '';
        }

        reset.onclick = () => {
            initVelocity.value = '';
            angle.value = '';
            projectileObj.x = 0;
            projectileObj.y = 0;
            projectileObj.element.style.left = '0px';
            projectileObj.element.style.bottom = '0px';

            let elements = document.getElementsByClassName('path');
            while(elements.length > 0){
                elements[0].parentNode.removeChild(elements[0]);
            }
            let yDist = document.getElementsByClassName('yDist');
            yDist[0].parentNode.removeChild(yDist[0]);
            let xDist = document.getElementsByClassName('xDist');
            xDist[0].parentNode.removeChild(xDist[0]);
        }

    </script>
</body>
</html>

Comments